/*
 * Copyright (c) 2024 endless-sky
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "device_command_handler.h"
#include "utils_log.h"
#include "utils_time.h"
#include <chrono>
#include <iomanip>
#include <sstream>
#include <ctime>
#include "common_version.h"
#include "common_product_definition.h"
#include <cstdlib>
#include <system_error>
#include "common_config_manager.h"
#include <sys/reboot.h>
#include <unistd.h>
#include <thread>
#include <chrono>

namespace El {
namespace Protocol {

void DeviceCommandHandler::RegisterMethodHandlers(
    std::unordered_map<std::string, std::function<nlohmann::json(const std::string &, const nlohmann::json &)>>
        &handlers)
{
    // 注册设备信息获取方法
    handlers["system.getInfo"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandleSystemGetInfo(id, params);
    };

    // 注册视频流获取方法
    handlers["cameras.getStream"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandleCamerasGetStream(id, params);
    };

    // 注册事件订阅相关方法
    handlers["events.subscribe"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandleEventsSubscribe(id, params);
    };

    handlers["events.unsubscribe"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandleEventsUnsubscribe(id, params);
    };

    handlers["system.getTime"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandleSystemGetTime(id, params);
    };

    handlers["system.setTime"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandleSystemSetTime(id, params);
    };

    // 注册NTP配置相关方法
    handlers["system.getNTPConfig"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandleSystemGetNTPConfig(id, params);
    };

    handlers["system.setNTPConfig"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandleSystemSetNTPConfig(id, params);
    };

    // 注册出厂重置方法
    handlers["system.factoryReset"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandleSystemFactoryReset(id, params);
    };

    // 注册系统重启方法
    handlers["system.restart"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandleSystemRestart(id, params);
    };
    
}

// 获取设备信息
nlohmann::json DeviceCommandHandler::HandleSystemGetInfo(const std::string &id, const nlohmann::json &params)
{
    EL_DEBUG("处理system.getInfo请求, 参数: {}", params.dump());

    // 检查必要参数
    if (!params.contains("device_id") || !params["device_id"].is_string()) {
        return CreateErrorResponse(id, 400, "缺少device_id参数或格式不正确");
    }

    std::string device_id = params["device_id"];

    // 获取设备型号
    std::string model;
    if (!Common::ProductDefinition::GetInstance().GetValue("device_model", model)) {
        EL_ERROR("获取设备型号失败");
        model = "未知设备";
    }

    // 获取固件版本
    std::string version;
    version = Common::VersionManager::GetInstance().GetVersionFull();
    if (version.empty()) {
        EL_ERROR("获取固件版本失败");
        version = "未知版本";
    }

    // 获取设备序列号：直接使用eth0的MAC地址（去除冒号）
    std::string serial_number;
    std::string mac = El::Network::Network::GetInstance().GetInterfaceMacAddress("eth0");
    // 移除MAC地址中的冒号
    for (char c : mac) {
        if (c != ':') {
            serial_number += c;
        }
    }
    EL_DEBUG("设备序列号(基于MAC地址): {}", serial_number);

    nlohmann::json info = {{"device_id", device_id},
                           {"model", model},
                           {"serial_number", serial_number},
                           {"firmware_version", version},
                           {"channel_count", 1}};

    return CreateSuccessResponse(id, info);
}

// 获取视频流
nlohmann::json DeviceCommandHandler::HandleCamerasGetStream(const std::string &id, const nlohmann::json &params)
{
    EL_DEBUG("处理cameras.getStream请求, 参数: {}", params.dump());

    // 检查必要参数
    if (!params.contains("channel") || !params["channel"].is_number()) {
        return CreateErrorResponse(id, 400, "缺少channel参数或格式不正确");
    }
    int channel = params["channel"];

    int stream_type = 0; // 默认使用主码流（0）
    if (params.contains("stream_type") && params["stream_type"].is_number()) {
        stream_type = params["stream_type"];
        // 验证码流类型
        if (stream_type < 0 || stream_type > 2) {
            return CreateErrorResponse(id, 400, "不支持的码流类型: " + std::to_string(stream_type));
        }
    }

    std::string protocol = "rtsp"; // 默认协议
    if (params.contains("protocol") && params["protocol"].is_string()) {
        protocol = params["protocol"];
    }

    std::string url;
    if (protocol == "rtsp") {
        // 获取设备IP地址
        std::string ip_address = El::Network::Network::GetInstance().GetInterfaceIpAddress("eth0");
        if (ip_address.empty() || ip_address == "127.0.0.1") {
            return CreateErrorResponse(id, 500, "无法获取设备IP地址");
        }

        // 构建RTSP URL
        std::string path = fmt::format("/live/{}/{}", channel, stream_type);
        url = fmt::format("rtsp://{}:554{}", ip_address, path);
    } else {
        return CreateErrorResponse(id, 400, "不支持的协议类型: " + protocol);
    }

    // 计算过期时间 (当前时间 + 1小时)
    auto now = std::chrono::system_clock::now();
    auto expires_time = now + std::chrono::hours(1);
    auto expires_time_t = std::chrono::system_clock::to_time_t(expires_time);

    std::stringstream ss;
    ss << std::put_time(std::gmtime(&expires_time_t), "%Y-%m-%dT%H:%M:%SZ");
    std::string expires_at = ss.str();

    nlohmann::json result = {{"url", url}, {"expires_at", expires_at}};

    return CreateSuccessResponse(id, result);
}

// 订阅事件
nlohmann::json DeviceCommandHandler::HandleEventsSubscribe(const std::string &id, const nlohmann::json &params)
{
    EL_DEBUG("处理events.subscribe请求, 参数: {}", params.dump());

    // 检查必要参数
    if (!params.contains("event_type") || !params["event_type"].is_string()) {
        return CreateErrorResponse(id, 400, "缺少event_type参数或格式不正确");
    }

    // 订阅信息
    Subscription sub;
    sub.id = "sub-" + std::to_string(std::chrono::system_clock::now().time_since_epoch().count());
    sub.event_type = params["event_type"];
    sub.active = true;

    // 设置创建时间
    auto now = std::chrono::system_clock::now();
    auto now_t = std::chrono::system_clock::to_time_t(now);
    std::stringstream ss;
    ss << std::put_time(std::gmtime(&now_t), "%Y-%m-%dT%H:%M:%SZ");
    sub.created_at = ss.str();

    // 保存订阅
    subscriptions_[sub.id] = sub;

    // 返回订阅信息
    nlohmann::json result = {{"subscription_id", sub.id}, {"status", "active"}};

    return CreateSuccessResponse(id, result);
}

// 取消订阅
nlohmann::json DeviceCommandHandler::HandleEventsUnsubscribe(const std::string &id, const nlohmann::json &params)
{
    EL_DEBUG("处理events.unsubscribe请求, 参数: {}", params.dump());

    // 检查必要参数
    if (!params.contains("subscription_id") || !params["subscription_id"].is_string()) {
        return CreateErrorResponse(id, 400, "缺少subscription_id参数或格式不正确");
    }

    std::string subscription_id = params["subscription_id"];

    // 查找订阅
    auto it = subscriptions_.find(subscription_id);
    if (it == subscriptions_.end()) {
        return CreateErrorResponse(id, 404, "找不到指定的订阅: " + subscription_id);
    }

    // 删除订阅
    subscriptions_.erase(it);

    // 返回成功
    nlohmann::json result = {{"subscription_id", subscription_id}, {"status", "canceled"}};

    return CreateSuccessResponse(id, result);
}

// 获取系统时间
nlohmann::json DeviceCommandHandler::HandleSystemGetTime(const std::string &id, const nlohmann::json &params)
{
    EL_DEBUG("处理system.getTime请求");
    (void)params; // 当前没有使用参数

    try {
        // 获取当前UTC时间 (微秒)
        uint64_t utc_microseconds = Utils::TimeManager::GetInstance().GetCurrentUtc();
        std::chrono::microseconds utc_duration(utc_microseconds);
        // 使用 system_clock 作为基准，因为它通常反映 wall clock time
        std::chrono::time_point<std::chrono::system_clock, std::chrono::microseconds> utc_tp(utc_duration);
        auto system_now_t = std::chrono::system_clock::to_time_t(utc_tp);

        // 将time_t (UTC秒数) 转换为 UTC tm 结构 (使用线程安全版本)
        std::tm utc_tm_now{};
        if (gmtime_r(&system_now_t, &utc_tm_now) == nullptr) {
            EL_ERROR("gmtime_r 失败");
            return CreateErrorResponse(id, 500, "无法转换UTC时间到tm结构");
        }

        // 格式化UTC时间为 YYYY-MM-DDTHH:MM:SSZ
        std::stringstream ss;
        ss << std::put_time(&utc_tm_now, "%Y-%m-%dT%H:%M:%SZ");

        // 响应包含utc_time和固定的time_zone
        nlohmann::json result = {{"utc_time", ss.str()}};
        result["time_zone"] = "Asia/Shanghai"; // Hardcode timezone

        return CreateSuccessResponse(id, result);

    } catch (const std::exception &e) {
        EL_ERROR("处理system.getTime时发生异常: {}", e.what());
        return CreateErrorResponse(id, 500, "获取系统时间时发生内部错误");
    } catch (...) {
        EL_ERROR("处理system.getTime时发生未知异常");
        return CreateErrorResponse(id, 500, "获取系统时间时发生未知内部错误");
    }
}

// 设置系统时间 (仅接受UTC时间)
nlohmann::json DeviceCommandHandler::HandleSystemSetTime(const std::string &id, const nlohmann::json &params)
{
    EL_DEBUG("处理system.setTime请求, 参数: {}", params.dump());

    // 检查必要参数 utc_time
    if (!params.contains("utc_time") || !params["utc_time"].is_string()) {
        return CreateErrorResponse(id, 400, "缺少utc_time参数或格式不正确");
    }
    std::string time_str_utc = params["utc_time"];

    // 可选：检查并处理时区参数（如果需要设置系统时区）
    // if (params.contains("time_zone") && params["time_zone"].is_string()) {
    //     std::string time_zone = params["time_zone"];
    //     // TODO: 实现设置系统时区的逻辑 (e.g., setenv("TZ", time_zone.c_str(), 1); tzset();)
    //     EL_INFO("系统时区已设置为: {}", time_zone);
    // }

    try {
        // 1. 验证并解析UTC时间字符串 (格式: YYYY-MM-DDTHH:mm:ssZ)
        if (time_str_utc.empty() || time_str_utc.back() != 'Z') {
            EL_ERROR("无效的UTC时间格式，必须以 'Z' 结尾: {}", time_str_utc);
            return CreateErrorResponse(id, 400, "无效的UTC时间格式，必须以 'Z' 结尾");
        }
        // 移除末尾的 'Z' 以便 std::get_time 解析
        std::string time_str_to_parse = time_str_utc.substr(0, time_str_utc.length() - 1);

        std::tm t = {};
        std::istringstream ss(time_str_to_parse);
        // 使用 %Y-%m-%dT%H:%M:%S 解析，因为 'Z' 已移除
        ss >> std::get_time(&t, "%Y-%m-%dT%H:%M:%S");

        if (ss.fail()) {
            // 检查是否是因为输入流结束后还有剩余字符导致的失败
            if (!ss.eof() || ss.bad()) {
                EL_ERROR("无效的时间格式，请使用 YYYY-MM-DDTHH:mm:ssZ : {}", time_str_utc);
                return CreateErrorResponse(id, 400, "无效的时间格式，请使用 YYYY-MM-DDTHH:mm:ssZ");
            }
            EL_WARN("时间字符串解析成功但可能包含额外字符或格式不完全匹配: {}", time_str_utc);
            ss.clear(ss.rdstate() & ~std::ios_base::failbit);
        }

        // 2. 将UTC tm结构转换为time_t (UTC秒数)
        // 使用 timegm (常见于 Linux glibc/musl)
        std::time_t time_t_utc = timegm(&t);
        if (time_t_utc == (std::time_t)-1) {
            // timegm 在某些实现中可能不会设置errno，但返回-1通常表示错误
            EL_ERROR("timegm 无法将UTC tm转换为time_t, time string: {}, parsed string: {}", time_str_utc,
                      time_str_to_parse);
            return CreateErrorResponse(id, 500, "无法将输入时间转换为有效的UTC时间戳 (timegm failed)");
        }

        // 3. 转换为UTC时间 (微秒)
        uint64_t utc_microseconds = static_cast<uint64_t>(time_t_utc) * 1000000;

        // 4. 设置系统UTC时间
        El::Utils::TimeManager::GetInstance().SetCurrentUtc(utc_microseconds);
        EL_INFO("系统UTC时间已设置为: {} (对应 time_t: {})", time_str_utc, time_t_utc);

        nlohmann::json result = {{"status", "success"}};
        return CreateSuccessResponse(id, result);

    } catch (const std::exception &e) {
        EL_ERROR("处理system.setTime时发生异常: {}", e.what());
        return CreateErrorResponse(id, 500, "设置系统时间时发生内部错误");
    } catch (...) {
        EL_ERROR("处理system.setTime时发生未知异常");
        return CreateErrorResponse(id, 500, "设置系统时间时发生未知内部错误");
    }
}

// 获取NTP配置
nlohmann::json DeviceCommandHandler::HandleSystemGetNTPConfig(const std::string &id, const nlohmann::json &params)
{
    EL_DEBUG("处理system.getNTPConfig请求");
    (void)params; // 当前没有使用参数

    nlohmann::json ntpConfig = Common::ConfigManager::GetInstance().GetConfig("/ntp");
    if (ntpConfig.is_null()) {
        EL_ERROR("无法获取NTP默认配置");
        return CreateErrorResponse(id, 500, "无法获取NTP配置信息");
    }

    bool enable = false;
    if (ntpConfig.contains("enable") && ntpConfig["enable"].is_boolean()) {
        enable = ntpConfig["enable"];
    } else {
        EL_WARN("NTP配置中缺少'enable'字段或类型不正确，默认为false");
    }

    std::vector<std::string> servers;
    if (ntpConfig.contains("servers") && ntpConfig["servers"].is_array()) {
        for (const auto &server : ntpConfig["servers"]) {
            if (server.is_string()) {
                servers.push_back(server.get<std::string>());
            } else {
                EL_WARN("NTP服务器列表中包含非字符串元素");
            }
        }
    } else {
        EL_WARN("NTP配置中缺少'servers'字段或类型不正确");
    }

    nlohmann::json result = {{"enable", enable}, {"servers", servers}};

    return CreateSuccessResponse(id, result);
}

// 设置NTP配置
nlohmann::json DeviceCommandHandler::HandleSystemSetNTPConfig(const std::string &id, const nlohmann::json &params)
{
    EL_DEBUG("处理system.setNTPConfig请求, 参数: {}", params.dump());

    // 检查参数
    if (!params.contains("enable") || !params["enable"].is_boolean()) {
        return CreateErrorResponse(id, 400, "缺少enable参数或格式不正确");
    }
    bool enable = params["enable"];

    std::vector<std::string> servers;
    if (enable) {
        if (!params.contains("servers") || !params["servers"].is_array() || params["servers"].empty()) {
            return CreateErrorResponse(id, 400, "启用NTP时必须提供非空的servers列表");
        }
        for (const auto &server : params["servers"]) {
            if (!server.is_string()) {
                return CreateErrorResponse(id, 400, "servers列表包含非字符串元素");
            }
            servers.push_back(server.get<std::string>());
        }
    } else {
        // 如果禁用NTP，则允许servers为空或不存在
        if (params.contains("servers") && params["servers"].is_array()) {
            for (const auto &server : params["servers"]) {
                if (!server.is_string()) {
                    return CreateErrorResponse(id, 400, "servers列表包含非字符串元素");
                }
                servers.push_back(server.get<std::string>());
            }
        }
    }

    // 获取当前配置，如果不存在则使用默认配置（确保有默认值）
    nlohmann::json currentConfig = Common::ConfigManager::GetInstance().GetConfig("/ntp");
    if (currentConfig.is_null()) {
        EL_ERROR("无法获取NTP默认配置用于更新");
        return CreateErrorResponse(id, 500, "无法更新NTP配置（无基础配置）");
    }

    // 更新配置值
    currentConfig["enable"] = enable;
    currentConfig["servers"] = servers;
    // 可以选择性地更新 interval，如果协议需要的话
    // if (params.contains("interval") && params["interval"].is_number_integer()) {
    //     currentConfig["interval"] = params["interval"];
    // }

    // 保存更新后的配置
    if (!Common::ConfigManager::GetInstance().SetConfig("/ntp", currentConfig)) {
        EL_ERROR("保存NTP配置失败");
        return CreateErrorResponse(id, 500, "保存NTP配置失败");
    }

    EL_INFO("NTP配置已更新: enable={}, servers=[{}]", enable, fmt::join(servers, ", "));

    // TODO: 应用NTP配置更改（例如，通知NTP客户端）

    nlohmann::json result = {{"status", "success"}};
    return CreateSuccessResponse(id, result);
}

// 出厂重置
nlohmann::json DeviceCommandHandler::HandleSystemFactoryReset(const std::string &id, const nlohmann::json &params)
{
    EL_DEBUG("处理system.factoryReset请求, 参数: {}", params.dump());

    // 检查可选参数
    bool preserve_network = false;
    if (params.contains("preserve_network") && params["preserve_network"].is_boolean()) {
        preserve_network = params["preserve_network"];
    }

    bool restart_system = true;
    if (params.contains("restart_system") && params["restart_system"].is_boolean()) {
        restart_system = params["restart_system"];
    }

    try {
        // 执行出厂重置操作
        Common::ConfigManager &configManager = Common::ConfigManager::GetInstance();
        
        nlohmann::json networkConfig;
        if (preserve_network) {
            // 保存当前网络配置
            networkConfig = configManager.GetConfig("/network");
            EL_INFO("保留网络配置进行出厂重置");
        }

        // 获取默认配置并重置
        if (!configManager.ResetToFactory()) {
            EL_ERROR("执行出厂重置失败");
            return CreateErrorResponse(id, 500, "出厂重置操作失败");
        }

        if (preserve_network && !networkConfig.is_null()) {
            // 恢复网络配置
            if (!configManager.SetConfig("/network", networkConfig, false)) {
                EL_WARN("恢复网络配置失败，但出厂重置已完成");
            }
        }

        EL_INFO("出厂重置完成, preserve_network={}, restart_system={}", preserve_network, restart_system);

        nlohmann::json result = {
            {"status", "success"},
            {"message", "出厂重置完成"},
            {"preserve_network", preserve_network},
            {"restart_system", restart_system}
        };

        if (restart_system) {
            result["restart_countdown"] = 5; // 5秒后重启
            // 启动异步重启任务
            std::thread([this]() {
                std::this_thread::sleep_for(std::chrono::seconds(5));
                HandleSystemRestart("internal", nlohmann::json::object());
            }).detach();
            EL_INFO("系统将在5秒后重启");
        }

        return CreateSuccessResponse(id, result);

    } catch (const std::exception &e) {
        EL_ERROR("处理system.factoryReset时发生异常: {}", e.what());
        return CreateErrorResponse(id, 500, "出厂重置时发生内部错误");
    } catch (...) {
        EL_ERROR("处理system.factoryReset时发生未知异常");
        return CreateErrorResponse(id, 500, "出厂重置时发生未知内部错误");
    }
}

// 系统重启
nlohmann::json DeviceCommandHandler::HandleSystemRestart(const std::string &id, const nlohmann::json &params)
{
    EL_DEBUG("处理system.restart请求, 参数: {}", params.dump());

    // 检查可选参数 - 重启延时时间（秒）
    int delay_seconds = 3;
    if (params.contains("delay") && params["delay"].is_number_integer()) {
        delay_seconds = params["delay"];
        // 限制延时时间在合理范围内
        if (delay_seconds < 0) delay_seconds = 0;
        if (delay_seconds > 60) delay_seconds = 60;
    }

    // 可选的重启原因说明
    std::string reason = "User requested";
    if (params.contains("reason") && params["reason"].is_string()) {
        reason = params["reason"];
    }

    try {
        EL_INFO("系统重启请求，原因: {}, 延时: {}秒", reason, delay_seconds);

        // 如果是内部调用（ID为"internal"），直接执行重启
        if (id == "internal") {
            EL_INFO("执行系统重启...");
            sync(); // 同步文件系统
            if (reboot(RB_AUTOBOOT) == -1) {
                EL_ERROR("系统重启失败: {}", strerror(errno));
            }
            return nlohmann::json::object(); // 不会执行到这里
        }

        // 对于API调用，返回成功响应然后异步执行重启
        nlohmann::json result = {
            {"status", "success"},
            {"message", "系统即将重启"},
            {"delay_seconds", delay_seconds},
            {"reason", reason}
        };

        // 启动异步重启任务
        if (delay_seconds > 0) {
            std::thread([delay_seconds]() {
                EL_INFO("等待{}秒后执行系统重启...", delay_seconds);
                std::this_thread::sleep_for(std::chrono::seconds(delay_seconds));
                EL_INFO("执行系统重启...");
                sync(); // 同步文件系统
                if (reboot(RB_AUTOBOOT) == -1) {
                    EL_ERROR("系统重启失败: {}", strerror(errno));
                }
            }).detach();
        } else {
            // 立即重启
            std::thread([]() {
                EL_INFO("执行系统重启...");
                sync(); // 同步文件系统
                if (reboot(RB_AUTOBOOT) == -1) {
                    EL_ERROR("系统重启失败: {}", strerror(errno));
                }
            }).detach();
        }

        return CreateSuccessResponse(id, result);

    } catch (const std::exception &e) {
        EL_ERROR("处理system.restart时发生异常: {}", e.what());
        return CreateErrorResponse(id, 500, "系统重启时发生内部错误");
    } catch (...) {
        EL_ERROR("处理system.restart时发生未知异常");
        return CreateErrorResponse(id, 500, "系统重启时发生未知内部错误");
    }
}
} // namespace Protocol
} // namespace El
